package top.superflow.service.view

import java.lang.reflect.Field

import top.superflow.constant.ViewConst
import top.superflow.lang.{CollectionUtils, ReflectUtils}
import top.superflow.service.view.dto.ColumnDef
import top.superflow.service.view.utils.{ActionUtils, ViewColumnUtils}

import scala.collection.mutable.ListBuffer

class BaseViewService {

  protected def  extractColumns[T](clz : Class[T]) : List[ColumnDef] = {
    var columns = ListBuffer[ColumnDef]()

    columns ++= extractColumnDefFromClass(clz)

    ViewColumnUtils.setOrderForCommonColumns(columns.toList)

    ViewColumnUtils.setPredefinedViewConf(columns.toList)

    columns = columns.sortWith((s, t) => s.displayOrder <= t.displayOrder)

    return columns.toList
  }


  protected def extractColumnDefFromClass(clz: Class[_]): List[ColumnDef] = {
    val columns = ListBuffer[ColumnDef]()

    if (clz == null) {
      return columns.toList
    }

    for (field <- clz.getDeclaredFields) {
      extractColumnFromField(columns, field)
    }

    addRowOperation(columns)

    columns.toList
  }

  private def addRowOperation(columns : ListBuffer[ColumnDef]): Unit ={
    val columnDef = new ColumnDef
    columnDef.setHeaderName(ViewConst.COLUMN_NAME_OPERATION)
    columnDef.setPinned(ActionUtils.DEFAULT_PINNED_POSITION)
    ActionUtils.setup(columnDef)

    columns += columnDef
  }

  private def extractColumnFromField(columns: ListBuffer[ColumnDef], field: Field): Unit = {
    if (field == null) {
      return
    }

    val columnDef = generateColumnFromField(field)

    if(CollectionUtils.isCollection(field.getType) && !shouldExcludeFromActionField(field)){
      ActionUtils.setup(columnDef)
    }

    columns += columnDef
  }



  private def generateColumnFromField(field : Field) : ColumnDef = {
    val columnDef = new ColumnDef
    columnDef.setHeaderName(field.getName)
    columnDef.setColId(field.getName)
    columnDef.setField(field.getName)

    return columnDef
  }

  private def shouldExcludeFromActionField(field : Field) : Boolean = {
    if(field == null){
      return true
    }

    if(ReflectUtils.isSingleGenericType(field.getGenericType, classOf[String])){
      return true
    }

    if(field.getType.isArray && field.getType.getComponentType == classOf[String]){
      return true
    }

    return false

  }
}
